package pl.zuiol.games.poker;

import com.hazelcast.core.*;
import pl.zuiol.games.poker.ui.GameTable;
import pl.zuiol.games.poker.util.Deck;
import pl.zuiol.games.poker.util.GameStage;
import pl.zuiol.games.poker.util.Hand;
import pl.zuiol.games.poker.util.Util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * User: Damian
 * Date: 21.06.11
 * Time: 18:52
 */

//Dealer nasluchuje zmian w etapie gry, tylko i wylacznie

public final class Dealer implements EntryListener{

    private static volatile Dealer dealer = null;
    private Deck deck = null;
    private int pot;
    private List<Player> players = null; // lista uzywana podczas pojedynczego rozdania, aktualizowana co rozdanie
    private HazelcastInstance hazelcastInstance = null;
    private IMap<String, Object> gameStatisticMap = null;
    private Player playerEndingStage = null;
    private boolean stopBidding = false;
    public static Dealer getDealer(HazelcastInstance instance, GameTable table){

        if(dealer == null){

           synchronized (Dealer.class){
               if(dealer == null){
                   dealer = new Dealer(instance, table);
               }
           }
        }
        return dealer;
    }

    private Dealer(HazelcastInstance instance, GameTable table){

        players = new ArrayList<Player>();
        hazelcastInstance = instance;
        gameStatisticMap = hazelcastInstance.getMap("Statistics");
        gameStatisticMap.put("PlayerEndingStage", "Dealer");
        gameStatisticMap.put("CurrentPlayer", "Dealer");
        gameStatisticMap.put("PlayerFolded", "Dealer");
        gameStatisticMap.put("Pot", 0);
        gameStatisticMap.addEntryListener(this, "PlayerFolded", true);
        gameStatisticMap.addEntryListener(this, "CurrentPlayer", true);
        gameStatisticMap.addEntryListener(this, "PlayerEndingStage", true);
    }

    public List<Player> handOut(){

        deck = new Deck();
        List<Player> playersWithCards = players;
        for (Player player : playersWithCards){
            player.setHand(new Hand(deck.drawFromDeck(), deck.drawFromDeck()));
        }
        return playersWithCards;
    }

    public void actualizePot(){

    }

    /*Sprawdzenie kto wygrywa rozdanie*/

    public void checkDealResult(List<Player> playersInGame){

    }



    @Override
    public void entryAdded(EntryEvent entryEvent) {
        Util.writeln(entryEvent.getName());
        if(entryEvent.getName().equals("c:Players")){
            if((Boolean)hazelcastInstance.getMap("Statistics").get("GameStarted") == true)
                return;
            Util.writeln("Czy chcesz rozpoczac gre zlozona z " + hazelcastInstance.getMap("Players").size() + " graczy?");
            if(Util.getText().equals("tak")){
                  startNewGame();
            }
        }
    }

    @Override
    public void entryRemoved(EntryEvent entryEvent) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void entryUpdated(EntryEvent entryEvent) {

        if(entryEvent.getKey().equals("PlayerFolded")){
            players.remove(entryEvent.getValue());
        }
        else if(entryEvent.getKey().equals("PlayerEndingStage")){
            int index = players.indexOf((Player)entryEvent.getValue());

            playerEndingStage = players.get((index - 1) >= 0 ? index - 1 : players.size() -1);
            stopBidding = false;
        }
        else if(entryEvent.getKey().equals("CurrentPlayer")){
            if(entryEvent.getValue().equals("Dealer")){
                int currentPlayerId = (Integer)gameStatisticMap.get("CurrentPlayerID");
                //if(players.get(currentPlayerId).equals(playerEndingStage)){
                if(stopBidding){
                    Util.writeln("Koniec licytacji - nast�pny etap");
                    stopBidding = false;
                    if(gameStatisticMap.get("CurrentStage") == GameStage.HandOut)
                    {
                    	gameStatisticMap.put("CurrentPot", 0);
                        gameStatisticMap.put("CurrentStage", GameStage.Floop);

                        gameStatisticMap.put("CurrentPlayer", players.get(0).getId());
                        gameStatisticMap.put("CurrentPlayerID", 0);
                        gameStatisticMap.put("PlayerEndingStage", players.get(0));

                    }
                    else if(gameStatisticMap.get("CurrentStage") == GameStage.Floop){
                    	/*gameStatisticMap.put("CurrentPot", 0);
                        gameStatisticMap.put("CurrentStage", GameStage.Turn);
                        gameStatisticMap.put("CurrentPlayer", players.get(1).getId());
                        gameStatisticMap.put("CurrentPlayerID", 1);
                        gameStatisticMap.put("PlayerEndingStage", players.get(1));*/
                    }
                    else if(gameStatisticMap.get("CurrentStage") == GameStage.Turn){
                    	/*gameStatisticMap.put("CurrentPot", 0);
                        gameStatisticMap.put("CurrentStage", GameStage.River);
                        gameStatisticMap.put("CurrentPlayer", players.get(1).getId());
                        gameStatisticMap.put("CurrentPlayerID", 1);
                        gameStatisticMap.put("PlayerEndingStage", players.get(1));*/
                    }
                    else if(gameStatisticMap.get("CurrentStage") == GameStage.River){
                        //gameStatisticMap.put("GameStarted", false);
                    }


                } //TODO zmiana
                else{
                    if(players.get((currentPlayerId + 2) % players.size()).equals(playerEndingStage)){
                        stopBidding = true;
                    }
                    gameStatisticMap.put("CurrentPlayerID", (currentPlayerId + 2) % players.size());
                    gameStatisticMap.put("CurrentPlayer", players.get((currentPlayerId + 2) % players.size()).getId());
                }

                // wymy�li� co si� dzieje jak player dokona� wyboru akcji
            }
        }
    }

    @Override
    public void entryEvicted(EntryEvent entryEvent) {
        //To change body of implemented methods use File | Settings | File Templates.
    }


    // pomocnicze funkcje uzywane w listenerach dla przejrzysto�ci
    public void startNewGame(){
    	
        gameStatisticMap.put("GameStarted", true);
        stopBidding = false;
        pot = 0;
        IMap<String, Player> playersMap = hazelcastInstance.getMap("Players");
        players.clear();
        Set<String> k = playersMap.keySet();
        ArrayList<String> a = new ArrayList<String>();
        a.addAll(k);
        Collections.sort(a);
        for(String i : a){
            players.add(playersMap.get(i));
        }

        players = handOut();
       
        
        
        pot += players.get(0).getFromPurse(5);
        players.get(0).setCurrentPot(5);
        pot += players.get(1).getFromPurse(10);
        players.get(1).setCurrentPot(10);
        playerEndingStage = players.get(1);

        for(Player pl : players){
            playersMap.put(pl.getId(), pl);
        }
        
        gameStatisticMap.put("CurrentPot", 10);
        gameStatisticMap.put("GlobalPot", pot);
        gameStatisticMap.put("CurrentStage", GameStage.HandOut);
        gameStatisticMap.put("CurrentPlayer", players.get(getIdAfterCurrentId(1)).getId());
        gameStatisticMap.put("CurrentPlayerID", 1);
        gameStatisticMap.put("PlayerEndingStage", players.get(1));
    }
    
    private int getIdAfterCurrentId(int id){
    	int size = players.size();
    	return (id + 1) % size;
    }
}